#include "table.h"
#include "hash_table_interface.h"
#include <math.h>
#include "../debug.h"


/* 2D HASH + Link */


static uint32_t HashTable_KeyCalc(uint32_t idx)
{
    return idx % HASH_TABLE_LEN;
}


hashTableErr_t HashTable_Create(table_t *pHashTable[][HASH_TABLE_LEN], table_t *pOriTable, uint32_t oriTableLen)
{
    uint32_t i, x, y, idx;
    tableEntry_t *pEntry = pOriTable;
    tableEntry_t **ppEntryTmp = NULL;

    for(i = 0; i < oriTableLen; i++)
    {
        idx = pEntry[i].idx;
        x = HashTable_KeyCalc(idx);
        y = (uint32_t)log10(idx);
        ppEntryTmp = (tableEntry_t **)&pHashTable[y][x];

        while(*ppEntryTmp != NULL)
        {
            if(idx == (*ppEntryTmp)->idx)
            {
                PRINT_ERROR("Original table error, multiple same index");
                return -HASH_TABLE_ERR_TABLE;
            }
            ppEntryTmp = (tableEntry_t **)&((*ppEntryTmp)->pExtra);
        }
        *ppEntryTmp = &pEntry[i];
    }

    return HASH_TABLE_ERR_NONE;
}


hashTableErr_t HashTable_Search(table_t *pHashTable[][HASH_TABLE_LEN], uint32_t idx, tableEntry_t **ppEntry)
{
    uint32_t x, y;
    tableEntry_t **ppEntryTmp = NULL;

    x = HashTable_KeyCalc(idx);
    y = (uint32_t)log10(idx);
    ppEntryTmp = (tableEntry_t **)&pHashTable[y][x];

    if(*ppEntryTmp == NULL)
    {
        // PRINT_WARN("Search failure");
        return -HASH_TABLE_ERR_SEARCH;
    }

    while((*ppEntryTmp)->idx != idx)
    {
        if((*ppEntryTmp)->pExtra == NULL)
        {
            // PRINT_WARN("Search failure");
            return -HASH_TABLE_ERR_SEARCH;
        }
        ppEntryTmp = (tableEntry_t **)&((*ppEntryTmp)->pExtra);
    }
    *ppEntry = *ppEntryTmp;

    return HASH_TABLE_ERR_NONE;
}

